#!/bin/bash
{
	#////////////////////////////////////
	# DietPi Function:
	# - Enables control and applies settings for specific hardware.
	#
	#////////////////////////////////////
	# Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com
	#
	#////////////////////////////////////
	#
	# Usage:
	readonly FP_SCRIPT='/boot/dietpi/func/dietpi-set_hardware'
	readonly AVAIABLE_COMMANDS="
Available commands:
$FP_SCRIPT	enableipv6		enable/disable
$FP_SCRIPT	preferipv4		enable/disable
$FP_SCRIPT	eth-forcespeed		10/100/1000/disable
$FP_SCRIPT	wifimodules		enable/disable/onboard_enable/onboard_disable
$FP_SCRIPT	wificountrycode		GB/US/DE/...
$FP_SCRIPT	bluetooth		enable/disable
$FP_SCRIPT	serialconsole		enable/disable		[tty(S|AMA|SAC)[0-9]] (optional Serial/UART device)
$FP_SCRIPT	i2c			enable/disable/khz
$FP_SCRIPT	spi			enable/disable
$FP_SCRIPT	soundcard		target_card (non-matching name for reset to default). Add '-eq' to target_card string to enable ALSA equalizer on card. HW:x,x (specify target card and device index eg: HW:9,1)
$FP_SCRIPT	remoteir		odroid_remote/justboom_ir_remote # Odroid/RPi only
$FP_SCRIPT	lcdpanel		target_panel (\"none\" to remove all)
$FP_SCRIPT	headless		enable/disable
$FP_SCRIPT	gpumemsplit		64/128/256... Range: 16-944, RPi only
$FP_SCRIPT	rpi-camera		enable/disable
$FP_SCRIPT	rpi-opengl		vc4-kms-v3d/vc4-kms-v3d-pi4/vc4-fkms-v3d/disable
$FP_SCRIPT	rpi3_usb_boot		enable
$FP_SCRIPT	rpi-eeprom
"	#////////////////////////////////////

	# Grab Inputs
	INPUT_DEVICE_NAME=${1,,}
	INPUT_DEVICE_VALUE=${2,,}
	# - Support for 1/0 inputs for enable/disable
	if [[ $INPUT_DEVICE_VALUE == '1' ]]; then

		INPUT_DEVICE_VALUE='enable'

	elif [[ $INPUT_DEVICE_VALUE == '0' ]]; then

		INPUT_DEVICE_VALUE='disable'

	fi
	INPUT_ADDITIONAL=$3

	# Import DietPi-Globals --------------------------------------------------------------
	. /boot/dietpi/func/dietpi-globals
	readonly G_PROGRAM_NAME='DietPi-Set_hardware'
	G_CHECK_ROOT_USER
	G_CHECK_ROOTFS_RW
	G_INIT
	# Import DietPi-Globals --------------------------------------------------------------

	# ARMbian uses armbianEnv.txt instead which requires different syntax
	if [[ -f '/boot/armbianEnv.txt' ]]; then

		ARMBIAN=1
		FP_UENV='/boot/armbianEnv.txt'

	# Sparky SBC uEnv.txt has been renamed to uenv.txt, lets support both variants
	else

		ARMBIAN=0
		FP_UENV='/tmp/uEnv.txt'
		for i in /boot/u{e,E}nv.txt; do [[ -f $i ]] && FP_UENV=$i && break; done
		unset -v i

	fi

	EXIT_CODE=0

	Unknown_Input_Name(){

		G_DIETPI-NOTIFY 2 "Unknown input name ($INPUT_DEVICE_NAME). Nothing has been applied."
		echo "$AVAIABLE_COMMANDS"
		EXIT_CODE=1

	}

	Unknown_Input_Mode(){

		G_DIETPI-NOTIFY 2 "Unknown input value ($INPUT_DEVICE_VALUE). Nothing has been applied."
		echo "$AVAIABLE_COMMANDS"
		EXIT_CODE=1

	}

	Unsupported_Input_Name(){

		G_DIETPI-NOTIFY 2 "Input name ($INPUT_DEVICE_NAME) is not supported by $G_HW_MODEL_NAME. Nothing has been applied."

	}

	Unsupported_Input_Mode(){

		G_DIETPI-NOTIFY 2 "Input value ($INPUT_DEVICE_VALUE) is not supported by $G_HW_MODEL_NAME. Nothing has been applied."

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# rpi-camera
	#/////////////////////////////////////////////////////////////////////////////////////
	RPi_Camera_Main(){

		(( $G_HW_MODEL > 9 )) && { Unsupported_Input_Name; return 1; } # Exit path for non-RPi

		if [[ $INPUT_DEVICE_VALUE == 'enable' ]]; then

			# Remove modules blacklist
			[[ -f '/etc/modprobe.d/dietpi-disable_rpi_camera.conf' ]] && G_EXEC rm /etc/modprobe.d/dietpi-disable_rpi_camera.conf

			# Enable video devices via extended start
			G_CONFIG_INJECT 'start_x=' 'start_x=1' /boot/config.txt

			# Requires 128 MiB memory split at least
			local gpu_mem=$(sed -n '/^[[:blank:]]*gpu_mem[_0-9]*=/{s/^[^=]*=//p;q}' /boot/config.txt)
			(( ${gpu_mem:-64} < 128 )) && INPUT_DEVICE_VALUE=128 Gpu_Memory_Split_Main

		elif [[ $INPUT_DEVICE_VALUE == 'disable' ]]; then

			# Comment extended start setting
			G_EXEC sed -i '/^[[:blank:]]*start_x=/c\#start_x=1' /boot/config.txt

			# Add modules blacklist, which are otherwise loaded by default since kernel 4.19/5.10
			echo -e 'blacklist bcm2835_codec\nblacklist bcm2835_v4l2\nblacklist bcm2835_isp' > /etc/modprobe.d/dietpi-disable_rpi_camera.conf

		else

			Unknown_Input_Mode

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# rpi3_usb_boot
	#/////////////////////////////////////////////////////////////////////////////////////
	RPi_USB_Boot_Main(){

		[[ $G_HW_MODEL == 3 && $G_HW_MODEL_NAME != *'+'* ]] || { Unsupported_Input_Name; return 1; } # Exit path for non-RPi3 nonplus

		if [[ $INPUT_DEVICE_VALUE == 'enable' ]]; then

			G_CONFIG_INJECT 'program_usb_boot_mode=' 'program_usb_boot_mode=1' /boot/config.txt

			cat << '_EOF_' > /etc/systemd/system/dietpi-rm_program_usb_boot_mode.service
[Unit]
Description=DietPi-rm_program_usb_boot_mode.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/bin/sed -i '/^[[:blank:]]*program_usb_boot_mode=/d' /boot/config.txt
ExecStartPre=/bin/systemctl disable dietpi-rm_program_usb_boot_mode
ExecStart=/bin/rm /etc/systemd/system/dietpi-rm_program_usb_boot_mode.service

[Install]
WantedBy=multi-user.target
_EOF_
			G_EXEC systemctl daemon-reload
			G_EXEC systemctl enable dietpi-rm_program_usb_boot_mode

		elif [[ $INPUT_DEVICE_VALUE == 'disable' ]]; then

			G_EXEC sed -i '/^[[:blank:]]*program_usb_boot_mode=/d' /boot/config.txt

			if [[ -f '/etc/systemd/system/dietpi-rm_program_usb_boot_mode.service' ]]; then

				G_EXEC systemctl disable --now dietpi-rm_program_usb_boot_mode
				G_EXEC rm /etc/systemd/system/dietpi-rm_program_usb_boot_mode.service

			fi

		else

			Unknown_Input_Mode

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# rpi-eeprom: https://www.raspberrypi.org/documentation/hardware/raspberrypi/booteeprom.md
	#/////////////////////////////////////////////////////////////////////////////////////
	RPi_EEPROM(){

		(( $G_HW_MODEL == 4 )) || { Unsupported_Input_Name; return 1; } # Exit path for non-RPi4

		# Install required APT package
		G_AGUP
		G_AGI rpi-eeprom

		# Update/flash new bootloader and VL805 USB firmware to EEPROM
		rpi-eeprom-update -a

		# Failsafe
		G_EXEC systemctl enable rpi-eeprom-update

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# gpumemsplit
	#/////////////////////////////////////////////////////////////////////////////////////
	Gpu_Memory_Split_Main()
	{
		(( $G_HW_MODEL > 9 )) && { Unsupported_Input_Name; return 1; } # Exit path for non-RPi

		# https://www.raspberrypi.org/documentation/configuration/config-txt/memory.md
		if disable_error=1 G_CHECK_VALIDINT "$INPUT_DEVICE_VALUE" 16 944
		then
			# Remove overridden "gpu_mem" setting
			grep -q '^[[:blank:]]*gpu_mem=' /boot/config.txt && G_EXEC sed -i '/^[[:blank:]]*gpu_mem=/d' /boot/config.txt

			local gpu_mem=$INPUT_DEVICE_VALUE
			G_CONFIG_INJECT 'gpu_mem_1024=' "gpu_mem_1024=$gpu_mem" /boot/config.txt
			(( $gpu_mem > 448 )) && gpu_mem=448
			G_CONFIG_INJECT 'gpu_mem_512=' "gpu_mem_512=$gpu_mem" /boot/config.txt
			(( $gpu_mem > 192 )) && gpu_mem=192
			G_CONFIG_INJECT 'gpu_mem_256=' "gpu_mem_256=$gpu_mem" /boot/config.txt

			# Disable VCSM if less than 32M are applied, since it is doomed to fail with cut-down firmware loaded.
			if (( $gpu_mem < 32 ))
			then
				# Blacklist kernel module
				G_EXEC eval 'echo '\''blacklist vc_sm_cma'\'' > /etc/modprobe.d/dietpi-disable_vcsm.conf'
				# Disable device via dtoverlay
				G_EXEC_DESC='Compiling device tree overlay: /boot/overlays/dietpi-disable_vcsm.dtbo'
				G_EXEC eval 'dtc -I dts -O dtb -o /boot/overlays/dietpi-disable_vcsm.dtbo <<< '\''/dts-v1/;
/plugin/;
/ {
	compatible = "brcm,bcm2835";
	fragment@0 {
		target-path = "/soc/vcsm";
		__overlay__ {
			status = "disabled";
		};
	};
};'\'''
				G_CONFIG_INJECT 'dtoverlay=dietpi-disable_vcsm' 'dtoverlay=dietpi-disable_vcsm' /boot/config.txt
			else
				grep -q 'dtoverlay=dietpi-disable_vcsm' /boot/config.txt && G_EXEC sed -i '/dtoverlay=dietpi-disable_vcsm/d' /boot/config.txt
				[[ -f '/boot/overlays/dietpi-disable_vcsm.dtbo' ]] && G_EXEC rm /boot/overlays/dietpi-disable_vcsm.dtbo
				[[ -f '/etc/modprobe.d/dietpi-disable_vcsm.conf' ]] && G_EXEC rm /etc/modprobe.d/dietpi-disable_vcsm.conf
			fi
		else
			Unknown_Input_Mode
		fi
	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# headless
	#/////////////////////////////////////////////////////////////////////////////////////
	Headless_Main(){

		if [[ $INPUT_DEVICE_VALUE == 'enable' ]]; then

			# RPi
			if (( $G_HW_MODEL < 10 )); then

				# Prevent any framebuffer from being allocated
				G_CONFIG_INJECT 'max_framebuffers=' 'max_framebuffers=0' /boot/config.txt
				# Splash cannot be seen anyway without video output
				G_CONFIG_INJECT 'disable_splash=' 'disable_splash=1' /boot/config.txt
				# hdmi_blanking should not play a role, however mode 1 should be generally preferred, which on idle disables HDMI output completely instead of just blanking the screen
				G_CONFIG_INJECT 'hdmi_blanking=' 'hdmi_blanking=1' /boot/config.txt
				# Disable HDMI hotplug detection, which requires it to be generally responsive/active
				G_CONFIG_INJECT 'hdmi_ignore_hotplug=' 'hdmi_ignore_hotplug=1' /boot/config.txt
				# Disable SDTV on RPi4 (default)
				G_EXEC sed -i '/^[[:blank:]]*enable_tvout=/c\#enable_tvout=0' /boot/config.txt

			# Odroid C2
			elif (( $G_HW_MODEL == 12 )); then

				G_CONFIG_INJECT 'setenv nographics ' 'setenv nographics "1"' /boot/boot.ini

			else

				Unsupported_Input_Name

			fi

			G_CONFIG_INJECT 'AUTO_SETUP_HEADLESS=' 'AUTO_SETUP_HEADLESS=1' /boot/dietpi.txt

		elif [[ $INPUT_DEVICE_VALUE == 'disable' ]]; then

			# RPi
			if (( $G_HW_MODEL < 10 )); then

				G_EXEC sed -i '/^[[:blank:]]*max_framebuffers=/c\#max_framebuffers=2' /boot/config.txt
				#G_EXEC sed -i '/^[[:blank:]]*disable_splash=/c\#disable_splash=0' /boot/config.txt
				G_EXEC sed -i '/^[[:blank:]]*hdmi_blanking=/c\#hdmi_blanking=0' /boot/config.txt
				G_EXEC sed -i '/^[[:blank:]]*hdmi_ignore_hotplug=/c\#hdmi_ignore_hotplug=0' /boot/config.txt
				G_EXEC sed -i '/^[[:blank:]]*enable_tvout=/c\#enable_tvout=0' /boot/config.txt

			# Odroid C2
			elif (( $G_HW_MODEL == 12 )); then

				G_CONFIG_INJECT 'setenv nographics ' 'setenv nographics "0"' /boot/boot.ini

			else

				Unsupported_Input_Name

			fi

			G_CONFIG_INJECT 'AUTO_SETUP_HEADLESS=' 'AUTO_SETUP_HEADLESS=0' /boot/dietpi.txt

		else

			Unknown_Input_Mode

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# remoteir
	#/////////////////////////////////////////////////////////////////////////////////////
	RemoteIR_Prereqs(){ G_AG_CHECK_INSTALL_PREREQ lirc; }

	RemoteIR_Reset(){

		# Disable JustBoom
		if (( $G_HW_MODEL < 10 )); then

			if [[ -f '/etc/systemd/system/justboom-ir-mpd.service' ]]; then

				G_EXEC systemctl disable --now justboom-ir-mpd
				G_EXEC rm /etc/systemd/system/justboom-ir-mpd.service

			fi
			[[ -d '/etc/systemd/system/justboom-ir-mpd.service.d' ]] && G_EXEC rm -R /etc/systemd/system/justboom-ir-mpd.service.d

			G_EXEC sed -i '/^[[:blank:]]*dtoverlay=gpio-ir/d' /boot/config.txt

		# Disable Odroids
		elif (( $G_HW_MODEL < 20 )); then

			if [[ -f '/etc/systemd/system/odroid-remote.service' ]]; then

				G_EXEC systemctl disable --now odroid-remote
				G_EXEC rm /etc/systemd/system/odroid-remote.service

			fi
			[[ -d '/etc/systemd/system/odroid-remote.service.d' ]] && G_EXEC rm -R /etc/systemd/system/odroid-remote.service.d

		fi

	}

	RemoteIR_Main(){

		(( $G_HW_MODEL > 19 )) && { Unsupported_Input_Name; return 1; } # Exit path for non-Odroid/non-RPi

		RemoteIR_Reset

		if [[ $INPUT_DEVICE_VALUE == 'odroid_remote' ]]; then

			(( $G_HW_MODEL > 9 )) || { Unsupported_Input_Mode; return 1; } # Exit path for non-Odroid

			RemoteIR_Prereqs

			# XU4 Cloudshell
			if (( $G_HW_MODEL == 11 )); then

				# Modules
				local string='options gpioplug_ir_recv gpio_nr=24 active_low=1'
				G_CONFIG_INJECT "$string" "$string" /etc/modprobe.d/odroid-cloudshell.conf
				G_CONFIG_INJECT 'gpio-ir-recv' 'gpio-ir-recv' /etc/modules
				G_CONFIG_INJECT 'gpioplug-ir-recv' 'gpioplug-ir-recv' /etc/modules

			# C2
			elif (( $G_HW_MODEL == 12 )); then

				# Module
				G_CONFIG_INJECT 'meson_ir' 'meson_ir' /etc/modules

			fi

			# Config
			cat << '_EOF_' > /etc/lirc/lircd.conf
begin remote

  name lircd.conf
  bits 16
  flags SPACE_ENC|CONST_LENGTH
  eps 30
  aeps 100

  header 9000 4500
  one 563 1688
  zero 563 564
  ptrail 563
  pre_data_bits 16
  pre_data 0x4DB2
  repeat 9000 2250
  toggle_bit_mask 0x0
      begin codes

          KEY_LEFT 0x9966
          KEY_RIGHT 0x837C
          KEY_UP 0x53AC
          KEY_DOWN 0x4BB4
          KEY_ENTER 0x738C
          KEY_HOME 0x41BE
          KEY_MUTE 0x11EE
          KEY_MENU 0xA35C
          KEY_BACK 0x59A6
          KEY_VOLUMEDOWN 0x817E
          KEY_VOLUMEUP 0x01FE
          KEY_POWER 0x3BC4

      end codes

end remote
_EOF_
			# Service
			G_EXEC systemctl enable --now lircd

		elif [[ $INPUT_DEVICE_VALUE == 'justboom_ir_remote' ]]; then

			(( $G_HW_MODEL > 9 )) && { Unsupported_Input_Mode; return 1; } # Exit path for non-RPi

			RemoteIR_Prereqs

			G_CONFIG_INJECT 'dtoverlay=gpio-ir' 'dtoverlay=gpio-ir,gpio_pin=25' /boot/config.txt

			# Config
			cat << '_EOF_' > /etc/lirc/hardware.conf
LIRCD_ARGS="--uinput"
LOAD_MODULES=true
DRIVER="default"
DEVICE="/dev/lirc0"
MODULES="lirc_rpi"
LIRCD_CONF=""
LIRCMD_CONF=""
_EOF_
			cat << '_EOF_' > /etc/lirc/lircd.conf
begin remote

  name  lircd.conf
  bits            5
  flags RC5|CONST_LENGTH
  eps            30
  aeps          100

  one           921   855
  zero          921   855
  plead         936
  pre_data_bits   8
  pre_data       0xA0
  gap          114211
  toggle_bit_mask 0x800

  suppress_repeat 5
  duty_cycle 300

  begin codes

        KEY_HOME 0x10
        KEY_POWER 0x11
        KEY_MUTE 0x12
        KEY_LEFT 0x13
        KEY_RIGHT 0x14
        KEY_ENTER 0x15
        KEY_MENU 0x16
        KEY_BACK 0x17
        KEY_VOLUMEDOWN 0x18
        KEY_VOLUMEUP 0x19
        KEY_UP 0x1A
        KEY_DOWN 0x1B

  end codes

end remote
_EOF_
			# MPD control
			G_AG_CHECK_INSTALL_PREREQ mpc

			cat << '_EOF_' > /root/.lircrc
begin
prog = irexec
button = KEY_ENTER
config = mpc toggle
end
begin
prog = irexec
button = KEY_VOLUMEUP
config = mpc volume +2
end
begin
prog = irexec
button = KEY_VOLUMEDOWN
config = mpc volume -2
end
begin
prog = irexec
button = KEY_RIGHT
config = mpc next
end
begin
prog = irexec
button = KEY_LEFT
config = mpc prev
end
begin
prog = irexec
button = KEY_UP
config = mpc seek +00:00:10
end
begin
prog = irexec
button = KEY_DOWN
config = mpc seek -00:00:10
end
begin
prog = irexec
button = KEY_BACK
config = mpc repeat on
end
begin
prog = irexec
button = KEY_MENU
config = mpc repeat off
end
_EOF_
			# Service
			cat << _EOF_ > /etc/systemd/system/justboom-ir-mpd.service
[Unit]
Description=justboom-ir-mpd (DietPi)
After=sound.target lircd.service lirc.service

[Service]
ExecStart=$(command -v irexec)

[Install]
WantedBy=default.target
_EOF_
			G_EXEC systemctl daemon-reload
			G_EXEC systemctl enable --now justboom-ir-mpd

		elif [[ $INPUT_DEVICE_VALUE != 'none' ]]; then

			Unknown_Input_Mode

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Ethernet force link speed
	#/////////////////////////////////////////////////////////////////////////////////////
	Eth_Force_Speed_Main(){

		if disable_error=1 G_CHECK_VALIDINT "$INPUT_DEVICE_VALUE" 1; then

			local speed_mbit=$INPUT_DEVICE_VALUE
			local iface="eth$(mawk 'NR==1' /run/dietpi/.network)"

			cat << _EOF_ > /etc/systemd/system/ethtool_force_speed.service
[Unit]
Description=ethtool force speed (DietPi)
Wants=network-online.target
After=network-online.target

[Service]
Type=oneshot
ExecStart=$(command -v ethtool) -s $iface speed $speed_mbit duplex full autoneg off

[Install]
WantedBy=ifup@$iface.service
_EOF_
			G_EXEC systemctl daemon-reload
			G_EXEC systemctl enable --now ethtool_force_speed

		elif [[ $INPUT_DEVICE_VALUE == 'disable' ]]; then # 0 is converted to "disable"

			if [[ -f '/etc/systemd/system/ethtool_force_speed.service' ]]; then

				G_EXEC systemctl disable --now ethtool_force_speed
				G_EXEC rm /etc/systemd/system/ethtool_force_speed.service

			fi
			[[ -d '/etc/systemd/system/ethtool_force_speed.service.d' ]] && G_EXEC rm -R /etc/systemd/system/ethtool_force_speed.service.d

		else

			Unknown_Input_Mode

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# RPi OpenGL
	#/////////////////////////////////////////////////////////////////////////////////////
	RPi_OpenGL_Main(){

		(( $G_HW_MODEL > 9 )) && { Unsupported_Input_Name; return 1; } # Exit path for non-RPi

		# Always remove previous VC4 overlay entry
		G_EXEC sed -i '/^[[:blank:]]*dtoverlay=vc4-/d' /boot/config.txt

		if [[ $INPUT_DEVICE_VALUE == 'vc4-kms-v3d' || $INPUT_DEVICE_VALUE == 'vc4-kms-v3d-pi4' || $INPUT_DEVICE_VALUE == 'vc4-fkms-v3d' ]]; then

			# Failsafe: Switch to correct full KMS overlay based on RPi model
			[[ $G_HW_MODEL != 4 && $INPUT_DEVICE_VALUE == 'vc4-kms-v3d-pi4' ]] && INPUT_DEVICE_VALUE='vc4-kms-v3d'
			[[ $G_HW_MODEK == 4 && $INPUT_DEVICE_VALUE == 'vc4-kms-v3d' ]] && INPUT_DEVICE_VALUE='vc4-kms-v3d-pi4'

			# GL packages
			local libegl1='libegl1'
			(( $G_DISTRO < 5 )) && libegl1+='-mesa'
			G_AG_CHECK_INSTALL_PREREQ libgl1-mesa-dri libgles2 $libegl1 mesa-utils

			G_CONFIG_INJECT "dtoverlay=$INPUT_DEVICE_VALUE" "dtoverlay=$INPUT_DEVICE_VALUE" /boot/config.txt

		elif [[ $INPUT_DEVICE_VALUE != 'disable' ]]; then

			Unknown_Input_Mode

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# lcdpanel eg: All non-HDMI/VGA based displays and monitors.
	#/////////////////////////////////////////////////////////////////////////////////////
	Lcd_Panel_Main(){

		local update_dietpitxt=1

		if [[ $INPUT_DEVICE_VALUE == 'odroid-lcd35' ]]; then

			Lcd_Panel_OdroidLCD35_Enable

		elif [[ $INPUT_DEVICE_VALUE == 'waveshare32' ]]; then

			Lcd_Panel_Waveshare32_Enable

		elif [[ $INPUT_DEVICE_VALUE == 'odroid-cloudshell' ]]; then

			Lcd_Panel_Odroidcloudshell_Enable

		elif [[ ${INPUT_DEVICE_VALUE,,} == 'esp01215e' ]]; then

			Lcd_Panel_ESP01215E_Enable

		elif [[ ${INPUT_DEVICE_VALUE,,} == 'allo-boss2-oled' ]]; then

			OLED_Allo_Boss2_Enable

		# Disable all
		elif [[ $INPUT_DEVICE_VALUE == 'none' ]]; then

			Lcd_Panel_Waveshare32_Disable
			Lcd_Panel_Odroidcloudshell_Disable
			Lcd_Panel_OdroidLCD35_Disable
			Lcd_Panel_ESP01215E_Disable
			OLED_Allo_Boss2_Disable

		else

			update_dietpitxt=0
			Unknown_Input_Mode

		fi

		# Update dietpi.txt entry?
		(( $update_dietpitxt )) && G_CONFIG_INJECT 'CONFIG_LCDPANEL=' "CONFIG_LCDPANEL=$INPUT_DEVICE_VALUE" /boot/dietpi.txt

	}

	Lcd_Panel_ESP01215E_Enable(){

		G_CONFIG_INJECT 'framebuffer_width=' 'framebuffer_width=1024' /boot/config.txt
		G_CONFIG_INJECT 'framebuffer_height=' 'framebuffer_height=600' /boot/config.txt
		G_CONFIG_INJECT 'SOFTWARE_CHROMIUM_RES_X=' "SOFTWARE_CHROMIUM_RES_X=1024" /boot/dietpi.txt
		G_CONFIG_INJECT 'SOFTWARE_CHROMIUM_RES_Y=' "SOFTWARE_CHROMIUM_RES_Y=600" /boot/dietpi.txt
		G_CONFIG_INJECT 'hdmi_force_hotplug=' 'hdmi_force_hotplug=1' /boot/config.txt
		G_CONFIG_INJECT 'hdmi_group=' 'hdmi_group=2' /boot/config.txt
		G_CONFIG_INJECT 'hdmi_mode=' 'hdmi_mode=87' /boot/config.txt
		G_CONFIG_INJECT 'hdmi_cvt=' 'hdmi_cvt=1024 600 60 6 0 0 0' /boot/config.txt
		G_CONFIG_INJECT 'hdmi_drive=' 'hdmi_drive=1' /boot/config.txt

	}

	Lcd_Panel_ESP01215E_Disable(){

		(( $G_HW_MODEL > 9 )) && return # Skip on non-RPi

		G_EXEC sed -i '/^[[:blank:]]*hdmi_force_hotplug=/c\#hdmi_force_hotplug=1' /boot/config.txt
		G_EXEC sed -i '/^[[:blank:]]*hdmi_group=/c\#hdmi_group=2' /boot/config.txt
		G_EXEC sed -i '/^[[:blank:]]*hdmi_mode=/c\#hdmi_mode=87' /boot/config.txt
		G_EXEC sed -i '/^[[:blank:]]*hdmi_cvt=/c\#hdmi_cvt=1024 600 60 6 0 0 0' /boot/config.txt
		G_EXEC sed -i '/^[[:blank:]]*hdmi_drive=/c\#hdmi_drive=1' /boot/config.txt

	}

	Lcd_Panel_Xorg_All_Enable(){

		# Xinput calibrator, fbset for con2fbmap
		G_AG_CHECK_INSTALL_PREREQ fbset xinput-calibrator xserver-xorg-input-evdev

		G_EXEC mkdir -p /etc/X11/xorg.conf.d

		# Create desktop icon for xcalibration
		# - NB: libinput replaces this in start menu

	}

	# Waveshare32
	Lcd_Panel_Waveshare32_Enable_X11(){

		cat << '_EOF_' > /etc/X11/xorg.conf.d/99-waveshare32_xorg.conf
Section "Device"
	Identifier	"Allwinner A10/A13 FBDEV"
	Driver		"fbdev"
	Option		"fbdev" "/dev/fb1"
	Option		"SwapbuffersWait" "true"
EndSection
_EOF_
		cat << '_EOF_' > /etc/X11/xorg.conf.d/99-waveshare32_calibration.conf
Section "InputClass"
	Identifier	"calibration"
	MatchProduct	"ADS7846 Touchscreen"
	Option		"Calibration" "219 3835 3984 219"
	Option		"SwapAxes" "1"
	Driver		"evdev"
EndSection
_EOF_
	}

	Lcd_Panel_Waveshare32_Enable(){

		(( $G_HW_MODEL > 19 )) && { Unsupported_Input_Mode; return 1; } # Exit path for non-RPi/non-Odroid

		# Disable 1st to reset any existing installations:
		Lcd_Panel_Waveshare32_Disable

		# RPi
		if (( $G_HW_MODEL < 10 )); then

			# X11
			Lcd_Panel_Xorg_All_Enable
			Lcd_Panel_Waveshare32_Enable_X11

			G_EXEC curl -sSfL https://github.com/waveshare/LCD-show/raw/master/waveshare32b-overlay.dtb -o /boot/overlays/waveshare32b.dtbo

			#consoleblank=0 no effect
			G_EXEC sed -i 's/rootwait/rootwait fbcon=map:10 fbcon=font:ProFont6x11 logo.nologo/' /boot/cmdline.txt

			G_CONFIG_INJECT 'dtparam=i2c_arm=' 'dtparam=i2c_arm=on' /boot/config.txt
			G_CONFIG_INJECT 'dtparam=spi=' 'dtparam=spi=on' /boot/config.txt

			# Set FB to match res
			G_CONFIG_INJECT 'framebuffer_width=' 'framebuffer_width=320' /boot/config.txt
			G_CONFIG_INJECT 'framebuffer_height=' 'framebuffer_height=240' /boot/config.txt
			G_CONFIG_INJECT 'SOFTWARE_CHROMIUM_RES_X=' "SOFTWARE_CHROMIUM_RES_X=320" /boot/dietpi.txt
			G_CONFIG_INJECT 'SOFTWARE_CHROMIUM_RES_Y=' "SOFTWARE_CHROMIUM_RES_Y=240" /boot/dietpi.txt

			G_CONFIG_INJECT 'dtoverlay=waveshare32b' 'dtoverlay=waveshare32b:rotate=270' /boot/config.txt

			# Swap input axis
			G_EXEC sed -i '/"SwapAxes"/c\	Option		"SwapAxes" "1"' /etc/X11/xorg.conf.d/99-waveshare32_calibration.conf

			# Move fb0 xorg.conf out the way: https://github.com/MichaIng/DietPi/issues/767
			[[ -f '/usr/share/X11/xorg.conf.d/99-fbturbo.conf' ]] && G_EXEC mv /usr/share/X11/xorg.conf.d/99-fbturbo.conf /usr/share/X11/99-fbturbo.conf

		# Odroids
		else

			# X11
			Lcd_Panel_Xorg_All_Enable
			Lcd_Panel_Waveshare32_Enable_X11

			# con2fbmap, maps console (1) to panel(2). Run during boot.
			cat << _EOF_ > /etc/systemd/system/con2fbmap.service
[Unit]
Description=con2fbmap

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=$(command -v con2fbmap) 1 2
ExecStop=$(command -v con2fbmap) 1 0

[Install]
WantedBy=multi-user.target
_EOF_
			G_EXEC systemctl daemon-reload
			G_EXEC systemctl enable con2fbmap

			G_CONFIG_INJECT 'spicc' 'spicc' /etc/modules
			G_CONFIG_INJECT 'fbtft_device' 'fbtft_device' /etc/modules

			echo 'options fbtft_device name=odroidc_tft32 rotate=270 gpios=reset:116,dc:115 speed=32000000 cs=0' > /etc/modprobe.d/waveshare32.conf

			# X11
			cat << '_EOF_' > /etc/X11/xorg.conf.d/99-waveshare32_xorg.conf
Section "Device"
	Identifier	"FBDEV"
	Driver		"fbdev"
	Option		"fbdev" "/dev/fb2"
	#Option		"SwapbuffersWait" "true"
EndSection
_EOF_
		fi

	}

	Lcd_Panel_Waveshare32_Disable(){

		# All
		[[ -f '/etc/X11/xorg.conf.d/99-waveshare32_calibration.conf' ]] && G_EXEC rm /etc/X11/xorg.conf.d/99-waveshare32_calibration.conf
		[[ -f '/etc/X11/xorg.conf.d/99-waveshare32_xorg.conf' ]] && G_EXEC rm /etc/X11/xorg.conf.d/99-waveshare32_xorg.conf
		[[ -f '/usr/share/applications/xinput_calibrator.desktop' ]] && G_EXEC rm /usr/share/applications/xinput_calibrator.desktop

		# RPi
		if (( $G_HW_MODEL < 10 )); then

			[[ -f '/boot/overlays/waveshare32b.dtbo' ]] && G_EXEC rm /boot/overlays/waveshare32b.dtbo
			G_EXEC sed -i 's/ fbcon=map:10 fbcon=font:ProFont6x11 logo.nologo//' /boot/cmdline.txt

			G_EXEC sed -i '/Waveshare 32 LCD/d' /boot/config.txt
			G_EXEC sed -i '/^[[:blank:]]*dtoverlay=waveshare32b/d' /boot/config.txt
			G_EXEC sed -i '/^[[:blank:]]*dtoverlay=ads7846,cs=1,penirq=17/d' /boot/config.txt
			G_EXEC sed -i '/^[[:blank:]]*dtoverlay=w1-gpio-pullup,gpiopin=4,extpullup=1/d' /boot/config.txt

			# Leave these enabled, just in case the user has other hardware that may use them.
			#G_EXEC sed -i '/^[[:blank:]]*dtparam=i2c_arm=/c\dtparam=i2c_arm=on' /boot/config.txt
			#G_EXEC sed -i '/^[[:blank:]]*dtparam=spi=/c\dtparam=spi=on' /boot/config.txt

			# Move fb0 xorg.conf back: https://github.com/MichaIng/DietPi/issues/767
			[[ -f '/usr/share/X11/99-fbturbo.conf' && ! -f '/usr/share/X11/xorg.conf.d/99-fbturbo.conf' ]] && G_EXEC mv /usr/share/X11/99-fbturbo.conf /usr/share/X11/xorg.conf.d/99-fbturbo.conf

		# Odroids
		elif (( $G_HW_MODEL < 20 )); then

			if [[ -f '/etc/systemd/system/con2fbmap.service' ]]; then

				G_EXEC systemctl disable --now con2fbmap
				G_EXEC rm -R /etc/systemd/system/con2fbmap.service*

			fi
			[[ -f '/etc/modprobe.d/waveshare32.conf' ]] && G_EXEC rm /etc/modprobe.d/waveshare32.conf
			G_EXEC sed -i '/^[[:blank:]]*spicc/d' /etc/modules
			G_EXEC sed -i '/^[[:blank:]]*fbtft_device/d' /etc/modules

		fi

	}

	# Odroid Cloudshell
	Lcd_Panel_Odroidcloudshell_Enable(){

		echo 'options fbtft_device name=hktft9340 busnum=1 rotate=270' > /etc/modprobe.d/odroid-cloudshell.conf

		G_CONFIG_INJECT 'spi_s3c64xx' 'spi_s3c64xx' /etc/modules
		G_CONFIG_INJECT 'fbtft_device' 'fbtft_device' /etc/modules
		echo 'fbtft_device' >> /etc/modules # XU4 4.9 workaround: https://github.com/MichaIng/DietPi/issues/926#issuecomment-299480918

	}

	Lcd_Panel_Odroidcloudshell_Disable(){

		[[ -f '/etc/modprobe.d/odroid-cloudshell.conf' ]] && G_EXEC rm /etc/modprobe.d/odroid-cloudshell.conf
		G_EXEC sed -i '/^[[:blank:]]*spi_s3c64xx/d' /etc/modules
		G_EXEC sed -i '/^[[:blank:]]*fbtft_device/d' /etc/modules

		# Cant run it on the fly, locks up device.
		#root@DietPi-XU4:~# modprobe -rf spi_s3c64xx
		#root@DietPi-XU4:~# modprobe -rf fbtft_device
		#Segmentation fault

	}

	# Odroid LCD 3.5
	Lcd_Panel_OdroidLCD35_Enable(){

		(( $G_HW_MODEL > 9 && $G_HW_MODEL < 20 )) || { Unsupported_Input_Mode; return 1; } # Exit path for non-Odroid

		# Reset to disabled
		Lcd_Panel_OdroidLCD35_Disable

		Lcd_Panel_Xorg_All_Enable

		cat << '_EOF_' > /etc/modprobe.d/odroid-lcd35.conf
options fbtft_device name=flexpfb rotate=90
options flexfb chip=ili9488
_EOF_
		local amodules=('fbtft_device' 'flexfb' 'sx865x')

		# C1/2
		(( $G_HW_MODEL == 11 )) || amodules+=('aml_i2c' 'pwm-meson' 'pwm-ctrl')

		for i in "${amodules[@]}"
		do

			# Enable modules now, as we need to detect pwm path for service
			G_EXEC modprobe "$i"
			G_CONFIG_INJECT "$i" "$i" /etc/modules

		done

		# Service
		# - XU4
		if (( $G_HW_MODEL == 11 )); then

			cat << _EOF_ > /etc/systemd/system/odroid-lcd35.service
[Unit]
Description=Odroid LCD 3.5

[Path]
PathExists=/dev/fb2

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=$(command -v setterm) -blank 0 -powersave off
ExecStart=$(command -v con2fbmap) 1 2
StandardOutput=tty

[Install]
WantedBy=multi-user.target
_EOF_
		# - C1/2
		else

			# Detect correct control files: https://github.com/MichaIng/DietPi/issues/2256
			local fp_control='/sys/devices/platform/pwm-ctrl'
			[[ -e '/sys/devices/pwm-ctrl/enable0' ]] && fp_control='/sys/devices/pwm-ctrl'

			cat << _EOF_ > /etc/systemd/system/odroid-lcd35.service
[Unit]
Description=Odroid LCD 3.5

[Path]
PathExists=/dev/fb2

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/dash -c 'echo 500000 > $fp_control/freq0'
ExecStart=/bin/dash -c 'echo 1 > $fp_control/enable0'
ExecStart=/bin/dash -c 'echo 1023 > $fp_control/duty0'
ExecStart=$(command -v setterm) -blank 0 -powersave off
ExecStart=$(command -v con2fbmap) 1 2
StandardOutput=tty

[Install]
WantedBy=multi-user.target
_EOF_
		fi
		G_EXEC systemctl daemon-reload
		G_EXEC systemctl enable odroid-lcd35

		# X.org
		[[ -f '/etc/X11/xorg.conf.d/exynos.conf' ]] && G_EXEC rm /etc/X11/xorg.conf.d/exynos.conf # XU4

		G_EXEC mkdir -p /etc/X11/xorg.conf.d
		cat << '_EOF_' > /etc/X11/xorg.conf.d/99-odroid-lcd35.conf
Section "Device"
	Identifier	"C fbdev"
	Driver		"fbdev"
	Option		"fbdev" "/dev/fb2"
EndSection
_EOF_
		# Default calibration
		cat << '_EOF_' > /etc/X11/xorg.conf.d/99-calibration.conf
Section "InputClass"
	Identifier	"calibration"
	MatchProduct	"SX865X Touchscreen"
	Option		"Calibration" "3854 155 3880 262"
	Option		"SwapAxes" "0"
EndSection
_EOF_
	}

	Lcd_Panel_OdroidLCD35_Disable(){

		[[ -f '/etc/X11/xorg.conf.d/99-calibration.conf' ]] && G_EXEC rm /etc/X11/xorg.conf.d/99-calibration.conf
		[[ -f '/etc/modprobe.d/odroid-lcd35.conf' ]] && G_EXEC rm /etc/modprobe.d/odroid-lcd35.conf
		if [[ -f '/etc/systemd/system/odroid-lcd35.service' ]]; then

			G_EXEC systemctl disable --now odroid-lcd35
			G_EXEC rm /etc/systemd/system/odroid-lcd35.service

		fi
		[[ -d '/etc/systemd/system/odroid-lcd35.service.d' ]] && G_EXEC rm -R /etc/systemd/system/odroid-lcd35.service.d
		[[ -f '/etc/X11/xorg.conf.d/99-odroid-lcd35.conf' ]] && G_EXEC rm /etc/X11/xorg.conf.d/99-odroid-lcd35.conf

	}

	OLED_Allo_Boss2_Enable(){

		(( $G_HW_MODEL > 9 )) && { Unsupported_Input_Mode; return 1; } # Exit path for non-RPi

		# Enable I2C
		INPUT_DEVICE_VALUE='enable' I2c_Main

		# Install further requirements
		G_AG_CHECK_INSTALL_PREREQ python3-{rpi.gpio,pil}

		# Download and install Python 3 script
		G_EXEC curl -sSfLO https://raw.githubusercontent.com/allocom/allo_boss2_oled_p3/main/boss2_oled_p3.tar.gz
		G_EXEC tar xf boss2_oled_p3.tar.gz
		[[ -d '/opt/allo_boss2_oled' ]] && G_EXEC rm -R /opt/allo_boss2_oled
		G_EXEC mv boss2_oled_p3 /opt/allo_boss2_oled

		# Create systemd service
		cat << _EOF_ > /etc/systemd/system/allo_boss2_oled.service
[Unit]
Description=Allo Boss2 OLED (DietPi)
After=sound.target

[Service]
SyslogIdentifier=Allo Boss2 OLED
ExecStart=$(command -v python3) /opt/allo_boss2_oled/boss2_oled.py
Restart=on-abort

[Install]
WantedBy=multi-user.target
_EOF_
		G_EXEC systemctl daemon-reload
		G_EXEC systemctl unmask allo_boss2_oled
		G_EXEC systemctl enable allo_boss2_oled

		# Remove possible files from Allo installer
		if [[ -f '/etc/systemd/system/boss2oled.service' ]]
		then
			G_EXEC systemctl disable --now boss2oled
			G_EXEC rm /etc/systemd/system/boss2oled.service
		fi
		[[ -d '/etc/systemd/system/boss2oled.service.d' ]] && G_EXEC rm -R /etc/systemd/system/boss2oled.service.d
		[[ -d '/opt/boss2_oled_p3' ]] && G_EXEC rm -R /opt/boss2_oled_p3
		[[ -d '/opt/boss2_oled' ]] && G_EXEC rm -R /opt/boss2_oled

	}

	OLED_Allo_Boss2_Disable(){

		(( $G_HW_MODEL > 9 )) && return # Skip on non-RPi

		# Disable and remove service
		if [[ -f '/etc/systemd/system/allo_boss2_oled.service' ]]
		then
			G_EXEC systemctl disable --now allo_boss2_oled
			G_EXEC rm /etc/systemd/system/allo_boss2_oled.service
		fi
		[[ -d '/etc/systemd/system/allo_boss2_oled.service.d' ]] && G_EXEC rm -R /etc/systemd/system/allo_boss2_oled.service.d

		# Remove scripts
		[[ -d '/opt/allo_boss2_oled' ]] && G_EXEC rm -R /opt/allo_boss2_oled

		# Disable I2C
		INPUT_DEVICE_VALUE='disable' I2c_Main

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# I2C
	#/////////////////////////////////////////////////////////////////////////////////////
	I2c_Main(){

		(( $G_HW_MODEL > 9 )) && { Unsupported_Input_Name; return 1; } # Exit path for non-RPi

		if [[ $INPUT_DEVICE_VALUE == 'enable' ]]; then

			# Check/install pre-reqs
			G_AG_CHECK_INSTALL_PREREQ python3-smbus i2c-tools

			# Kernel modules
			G_CONFIG_INJECT 'i2c-bcm2708' 'i2c-bcm2708' /etc/modules
			G_CONFIG_INJECT 'i2c-dev' 'i2c-dev' /etc/modules

			# config.txt
			G_CONFIG_INJECT 'dtparam=i2c_arm=' 'dtparam=i2c_arm=on' /boot/config.txt

			# DietPi-Software, set installed
			[[ -f '/boot/dietpi/.installed' ]] && G_EXEC sed -i '/^aSOFTWARE_INSTALL_STATE\[72\]=/c\aSOFTWARE_INSTALL_STATE\[72\]=2' /boot/dietpi/.installed

		elif [[ $INPUT_DEVICE_VALUE == 'disable' ]]; then

			# Kernel modules
			G_EXEC sed -i '/^[[:blank:]]*i2c-bcm2708/d' /etc/modules
			G_EXEC sed -i '/^[[:blank:]]*i2c-dev/d' /etc/modules

			# config.txt
			G_EXEC sed -Ei 's/^[[:blank:]]*(dtparam=i2c.*)$/#\1/' /boot/config.txt

		# Set baudrate (kHz) | valid int
		elif disable_error=1 G_CHECK_VALIDINT "$INPUT_DEVICE_VALUE" 2 10000000; then

			G_CONFIG_INJECT 'dtparam=i2c_arm_baudrate=' "dtparam=i2c_arm_baudrate=$(( $INPUT_DEVICE_VALUE * 1000 ))" /boot/config.txt

			# Inform user
			INPUT_DEVICE_VALUE+=' kHz'

		else

			Unknown_Input_Mode

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# SPI: https://github.com/raspberrypi/documentation/tree/master/hardware/raspberrypi/spi
	#/////////////////////////////////////////////////////////////////////////////////////
	SPI_Main(){

		(( $G_HW_MODEL > 9 )) && { Unsupported_Input_Name; return 1; } # Exit path for non-RPi

		if [[ $INPUT_DEVICE_VALUE == 'enable' ]]; then

			# config.txt
			G_CONFIG_INJECT 'dtparam=spi=' 'dtparam=spi=on' /boot/config.txt

			# Enable in runtime seems to be possible?
			#dtparam spi=on

		elif [[ $INPUT_DEVICE_VALUE == 'disable' ]]; then

			# config.txt
			G_CONFIG_INJECT 'dtparam=spi=' 'dtparam=spi=off' /boot/config.txt
			G_EXEC sed -i '/^[[:blank:]]*dtoverlay=spi[0-9]-[0-9]cs/d' /boot/config.txt # Alternative SPI interfaces and chip select lines

			# Disable in runtime seems to be possible?
			#dtparam spi=off

		else

			Unknown_Input_Mode

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Bluetooth
	#/////////////////////////////////////////////////////////////////////////////////////

	Bluetooth_Main(){

		local aBLUETOOTH_MODULES=(

			'bluetooth'
			'bnep'
			'btbcm' # RPi3 Broadcom onboard
			'rfcomm' # BPi Pro/M2+ and others
			'hidp' # BPi Pro/M2+ and others
			'hci_uart'

		)

		if [[ $INPUT_DEVICE_VALUE == 'disable' ]]; then

			# RPi
			if (( $G_HW_MODEL < 10 )) && (( $G_HW_ONBOARD_WIFI )); then

				systemctl disable --now hciuart 2> /dev/null
				# Disable onboard Bluetooth via device tree overlay
				G_CONFIG_INJECT 'dtoverlay=disable-bt' 'dtoverlay=disable-bt' /boot/config.txt

			# ASUS TB
			elif (( $G_HW_MODEL == 52 )); then

				systemctl disable --now hciuart 2> /dev/null

			# Broadcom-based models that need brcm_patchram_plus
			elif [[ $G_HW_MODEL == 6[12] ]]; then

				systemctl disable --now brcm_patchram_plus 2> /dev/null

			fi

			systemctl disable --now bluetooth 2> /dev/null

			# Unload and blacklist kernel modules, bluetooth last
			> /etc/modprobe.d/dietpi-disable_bluetooth.conf
			for ((i=$(( ${#aBLUETOOTH_MODULES[@]} - 1 )); i>=0; i--))
			do

				modprobe -r "${aBLUETOOTH_MODULES[$i]}" 2> /dev/null
				echo "blacklist ${aBLUETOOTH_MODULES[$i]}" >> /etc/modprobe.d/dietpi-disable_bluetooth.conf

			done

			# Purge packages
			if (( $G_DIETPI_INSTALL_STAGE >= 0 )); then

				G_AGP bluez bluez-firmware pi-bluetooth rtl8723ds-firmware
				G_AGA

			fi

		elif [[ $INPUT_DEVICE_VALUE == 'enable' ]]; then

			# Remove kernel module blacklist
			[[ -f '/etc/modprobe.d/dietpi-disable_bluetooth.conf' ]] && G_EXEC rm /etc/modprobe.d/dietpi-disable_bluetooth.conf

			# RPi
			if (( $G_HW_MODEL < 10 )) && (( $G_HW_ONBOARD_WIFI )); then

				# Login console on ttyAMA0 must be disabled: https://github.com/MichaIng/DietPi/issues/2607#issuecomment-470523194
				if systemctl -q is-active serial-getty@ttyAMA0; then

					G_WHIP_YESNO '[WARNING] A serial login console is currently active on ttyAMA0\n
Do you want to continue and disable the serial login console?' || return 1
					INPUT_DEVICE_VALUE='disable' INPUT_ADDITIONAL='ttyAMA0' Serial_Main

				fi

				# Remove dtoverlay
				G_EXEC sed -i '/^[[:blank:]]*dtoverlay=disable-bt/d' /boot/config.txt

				G_AG_CHECK_INSTALL_PREREQ pi-bluetooth

			else

				# ROCK Pi S: https://wiki.radxa.com/RockpiS/Debian#Bluetooth
				local rockpis
				(( $G_HW_MODEL == 73 )) && apt-cache show rtl8723ds-firmware &> /dev/null && rockpis='rtl8723ds-firmware'

				# bluez-firmware: BCM203x dongles: https://packages.debian.org/bluez-firmware
				G_AG_CHECK_INSTALL_PREREQ bluez bluez-firmware $rockpis

			fi

			# Load kernel modules, bluetooth first
			for i in "${aBLUETOOTH_MODULES[@]}"
			do

				modprobe "$i" 2> /dev/null

			done

			# Failsafe: Unblock all Bluetooth adapters if rfkill is installed
			command -v rfkill > /dev/null && rfkill unblock bluetooth

			# Broadcom-based models that need brcm_patchram_plus
			if [[ $G_HW_MODEL == 6[12] ]]; then

				G_EXEC systemctl enable --now brcm_patchram_plus

			fi

			G_EXEC systemctl enable --now bluetooth

			# RPi
			(( $G_HW_MODEL > 9 )) || (( ! $G_HW_ONBOARD_WIFI )) || G_EXEC systemctl enable hciuart

		else

			Unknown_Input_Mode

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Network
	#/////////////////////////////////////////////////////////////////////////////////////

	Enable_IPv6(){

		if [[ ! -d '/proc/sys/net/ipv6' ]]; then

			G_DIETPI-NOTIFY 1 'IPv6 is not supported or disabled on kernel level. Aborting...'
			EXIT_CODE=1
			return 1

		elif [[ $INPUT_DEVICE_VALUE == 'enable' ]]; then

			[[ -f '/etc/sysctl.d/dietpi-disable_ipv6.conf' ]] && rm /etc/sysctl.d/dietpi-disable_ipv6.conf
			# - Apply to current session:
			#	- "all" => all existing interfaces
			#	- "default" => all future interfaces
			echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6
			echo 0 > /proc/sys/net/ipv6/conf/default/disable_ipv6
			# - Add IPv6 specific host entries
			G_CONFIG_INJECT '::1[[:blank:]]' '::1 localhost ip6-localhost ip6-loopback' /etc/hosts
			G_CONFIG_INJECT 'ff02::1[[:blank:]]' 'ff02::1 ip6-allnodes' /etc/hosts
			G_CONFIG_INJECT 'ff02::2[[:blank:]]' 'ff02::2 ip6-allrouters' /etc/hosts
			# - dietpi.txt entry
			G_CONFIG_INJECT 'CONFIG_ENABLE_IPV6=' 'CONFIG_ENABLE_IPV6=1' /boot/dietpi.txt

		elif [[ $INPUT_DEVICE_VALUE == 'disable' ]]; then

			echo -e 'net.ipv6.conf.all.disable_ipv6=1\nnet.ipv6.conf.default.disable_ipv6=1' > /etc/sysctl.d/dietpi-disable_ipv6.conf
			sysctl -qp /etc/sysctl.d/dietpi-disable_ipv6.conf
			# - Comment IPv6 specific host entries
			sed -i 's/^::1[[:blank:]]/#::1 /' /etc/hosts
			sed -i 's/^ff02::1[[:blank:]]/#ff02::1 /' /etc/hosts
			sed -i 's/^ff02::2[[:blank:]]/#ff02::2 /' /etc/hosts
			# - dietpi.txt entry
			G_CONFIG_INJECT 'CONFIG_ENABLE_IPV6=' 'CONFIG_ENABLE_IPV6=0' /boot/dietpi.txt
			# - Stop preferring IPv4, if IPv6 is disabled, to reduce obsolete/confusing entries
			INPUT_DEVICE_VALUE='disable' Prefer_IPv4

		else

			Unknown_Input_Mode
			return 1

		fi

		# Failsafe: Comment "disable_ipv6" entries in all other sysctl config files
		local i
		for i in /etc/sysctl{,.d/*}.conf
		do
			[[ $i != '/etc/sysctl.d/dietpi-disable_ipv6.conf' && -f $i ]] || continue
			grep -q '^[[:blank:]]*net.ipv6.conf.[^[:blank:]]*.disable_ipv6[[:blank:]]*=' "$i" || continue
			i=$(readlink -f $i) # https://github.com/MichaIng/DietPi/issues/3003#issuecomment-669464255
			sed -i 's/^[[:blank:]]*net.ipv6.conf.[^[:blank:]]*.disable_ipv6[[:blank:]]*=/#&/' "$i"
		done

	}

	Prefer_IPv4(){

		if [[ $INPUT_DEVICE_VALUE == 'enable' ]]; then

			# APT force IPv4
			echo 'Acquire::ForceIPv4 "true";' > /etc/apt/apt.conf.d/99-dietpi-force-ipv4
			# Wget prefer IPv4
			G_CONFIG_INJECT 'prefer-family[[:blank:]]*=' 'prefer-family = IPv4' /etc/wgetrc
			# dietpi.txt entry
			G_CONFIG_INJECT 'CONFIG_PREFER_IPV4=' 'CONFIG_PREFER_IPV4=1' /boot/dietpi.txt

		elif [[ $INPUT_DEVICE_VALUE == 'disable' ]]; then

			# APT allow IPv6
			[[ -f '/etc/apt/apt.conf.d/99-dietpi-force-ipv4' ]] && rm /etc/apt/apt.conf.d/99-dietpi-force-ipv4
			# Wget back to default
			sed -i 's/^[[:blank:]]*prefer-family[[:blank:]]*=/#&/' /etc/wgetrc
			# dietpi.txt entry
			G_CONFIG_INJECT 'CONFIG_PREFER_IPV4=' 'CONFIG_PREFER_IPV4=0' /boot/dietpi.txt

		else

			Unknown_Input_Mode
			return 1

		fi

		# Failsafe: Comment "ForceIPv[46]" entries in all other APT config files
		local i
		for i in /etc/apt/apt.conf.d/*
		do
			[[ ! -f $i || $i == *'99-dietpi-force-ipv4' ]] && continue
			sed -i 's/^[[:blank:]]*Acquire::ForceIPv[46][[:blank:]]*=/#&/' "$i"
		done

	}

	Wifi_Modules_Main(){

		# Estimate module list
		# - All
		local aWIFI_MODULES=('cfg80211')

		# + RPi with onboard WiFi
		if (( $G_HW_ONBOARD_WIFI )); then

			aWIFI_MODULES+=('brcmfmac' 'brcmutil')

		# + NanoPi K1 Plus
		elif (( $G_HW_MODEL == 67 )); then

			aWIFI_MODULES+=('8189es')

		# + PINE A64 / Pinebook / ASUS Tinker Board (onboard)
		elif (( $G_HW_MODEL == 40 || $G_HW_MODEL == 44 || $G_HW_MODEL == 52 )); then

			aWIFI_MODULES+=('8723bs')

		# + NanoPi NEO Air
		elif (( $G_HW_MODEL == 64 )); then

			# 4.9 uses brcm, only enable dhd for 3.x
			if [[ -d '/boot/dtb' ]]; then

				aWIFI_MODULES+=('brcmfmac' 'brcmutil')

			else

				aWIFI_MODULES+=('dhd')

			fi

		# + NanoPi M3/T3/Fire3
		elif (( $G_HW_MODEL == 62 )); then

			aWIFI_MODULES+=('bcmdhd')

		fi

		# APT packages
		local apackages=('iw' 'wireless-tools' 'crda' 'wpasupplicant')

		if [[ $INPUT_DEVICE_VALUE == 'disable' ]]; then

			# Disable onboard WiFi as well
			(( $G_HW_ONBOARD_WIFI )) && INPUT_DEVICE_VALUE='onboard_disable' Wifi_Modules_Main

			# Reset blacklists and remove powersaving settings
			> /etc/modprobe.d/dietpi-disable_wifi.conf
			[[ -f '/etc/modprobe.d/dietpi-disable_wifi_powersaving.conf' ]] && rm /etc/modprobe.d/dietpi-disable_wifi_powersaving.conf

			# cfg80211 last
			for ((i=$(( ${#aWIFI_MODULES[@]} - 1 )); i>=0; i--))
			do
				echo "blacklist ${aWIFI_MODULES[$i]}" >> /etc/modprobe.d/dietpi-disable_wifi.conf
				modprobe -rf "${aWIFI_MODULES[$i]}" 2> /dev/null
			done

			if G_WHIP_YESNO 'Would you like to purge all WiFi related APT packages?
 - (NOTICE) This will free up space, but an internet-capable Ethernet connection is required to re-enable WiFi functionality.'; then

				G_AGP "${apackages[@]}"
				G_AGA

			fi

		elif [[ $INPUT_DEVICE_VALUE == 'enable' ]]; then

			# Disable known powersaving options for specific chipsets
			cat << _EOF_ > /etc/modprobe.d/dietpi-disable_wifi_powersaving.conf
options 8192cu rtw_power_mgnt=0
options 8188eu rtw_power_mgnt=0
# OPi Plus
options 8189es rtw_power_mgnt=0
# Pine A64
options 8723bs rtw_power_mgnt=0
# Sparky SBC
options wlan_8192eu rtw_power_mgnt=0
# - https://github.com/sparky-sbc/sparky-test/tree/master/rtl8812au
options wlan_8812au rtw_power_mgnt=0
_EOF_

			# Remove blacklists
			[[ -f '/etc/modprobe.d/dietpi-disable_wifi.conf' ]] && rm /etc/modprobe.d/dietpi-disable_wifi.conf

			G_DIETPI-NOTIFY 2 'Please wait, enabling WiFi modules...'

			# cfg80211 first
			for i in "${aWIFI_MODULES[@]}"
			do
				modprobe "$i" 2> /dev/null
			done

			# Delay to allow modules + WPA2-Enterprise being fully loaded and avoid device not found error
			sleep 8

			# Install required APT packages
			G_AG_CHECK_INSTALL_PREREQ "${apackages[@]}" || EXIT_CODE=1

			# Failsafe, unblock all WiFi adapters: https://github.com/MichaIng/DietPi/issues/1627
			command -v rfkill > /dev/null && rfkill unblock wifi

		elif [[ $INPUT_DEVICE_VALUE == 'onboard_enable' ]]; then

			(( $G_HW_ONBOARD_WIFI )) || { Unsupported_Input_Mode; return 1; }

			# Remove dtoverlay
			sed -i '/^[[:blank:]]*dtoverlay=disable-wifi/d' /boot/config.txt

		elif [[ $INPUT_DEVICE_VALUE == 'onboard_disable' ]]; then

			(( $G_HW_ONBOARD_WIFI )) || { Unsupported_Input_Mode; return 1; }

			# Disable onboard WiFi via dtoverlay
			G_CONFIG_INJECT 'dtoverlay=disable-wifi' 'dtoverlay=disable-wifi' /boot/config.txt

		else

			Unknown_Input_Mode

		fi

		# Update our networking file (refresh active wlan index)
		/boot/dietpi/func/obtain_network_details

	}

	Wifi_Countrycode_Main(){

		# Use country code from command input: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
		INPUT_DEVICE_VALUE=${INPUT_DEVICE_VALUE^^} # Needs to be uppercase while all input is made lowercase (ToDo)
		if [[ $INPUT_DEVICE_VALUE == [[:upper:]][[:upper:]] ]]; then

			# Update /etc/default/crda to apply country code via udev rules
			G_CONFIG_INJECT 'REGDOMAIN=' "REGDOMAIN=$INPUT_DEVICE_VALUE" /etc/default/crda || EXIT_CODE=1

			# Apply country code now
			iw reg set "$INPUT_DEVICE_VALUE" || EXIT_CODE=1

			# Update dietpi.txt with new value
			G_CONFIG_INJECT 'AUTO_SETUP_NET_WIFI_COUNTRY_CODE=' "AUTO_SETUP_NET_WIFI_COUNTRY_CODE=$INPUT_DEVICE_VALUE" /boot/dietpi.txt

		else

			Unknown_Input_Mode

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# serialconsole
	#/////////////////////////////////////////////////////////////////////////////////////

	Serial_Main(){

		#-------------------------------------------------------------------------------------
		# Enable
		if [[ $INPUT_DEVICE_VALUE == 'enable' ]]; then

			# Enable for specific Serial/UART device
			if [[ $INPUT_ADDITIONAL ]]; then

				# RPi: Warn if on RPi ttyAMA0 is about to be enabled while Bluetooth is up
				if [[ $G_HW_MODEL == [0-9] && $INPUT_ADDITIONAL == 'ttyAMA0' ]] && systemctl -q is-active hciuart; then

					G_WHIP_YESNO '[WARNING] ttyAMA0 is currently used by Bluetooth\n
Do you want to continue and DISABLE Bluetooth now?' || return 1
					INPUT_DEVICE_VALUE='disable' Bluetooth_Main

				fi

				G_DIETPI-NOTIFY 2 "Enabling serial-getty on: /dev/$INPUT_ADDITIONAL"
				G_EXEC systemctl unmask "serial-getty@$INPUT_ADDITIONAL"
				G_EXEC systemctl enable "serial-getty@$INPUT_ADDITIONAL"
				# Start now if device (already) exists
				[[ -e /dev/$INPUT_ADDITIONAL ]] && G_EXEC systemctl start "serial-getty@$INPUT_ADDITIONAL"

				# Allow root login on selected TTY if not enabled by default. This file has been removed with Debian Bullseye and is not respected by its default PAM rules.
				(( $G_DISTRO < 6 )) && G_CONFIG_INJECT "$INPUT_ADDITIONAL" "$INPUT_ADDITIONAL" /etc/securetty

				# Enable boot messages depending on device
				# - RPi
				if (( $G_HW_MODEL < 10 )); then

					grep -q "console=$INPUT_ADDITIONAL" /boot/cmdline.txt || sed -i "/root=/s/[[:blank:]]*$/ console=$INPUT_ADDITIONAL,115200/" /boot/cmdline.txt

				# - Odroid C2
				elif (( $G_HW_MODEL == 12 )); then

					local old=
					[[ -f '/boot/boot.ini' ]] && old=$(grep -m1 '^setenv condev "' /boot/boot.ini) || return 0
					[[ $old == *"console=$INPUT_ADDITIONAL"* ]] && return 0
					old=$(cut -d \" -f 2 <<< "$old")
					G_CONFIG_INJECT 'setenv condev "' "setenv condev \"$old console=$INPUT_ADDITIONAL,115200n8\"" /boot/boot.ini

				# - Odroid XU4
				elif (( $G_HW_MODEL == 11 )); then

					local old=
					[[ -f '/boot/boot.ini' ]] && old=$(grep -m1 '^setenv bootrootfs "' /boot/boot.ini) || return 0
					[[ $old == *"console=$INPUT_ADDITIONAL"* ]] && return 0
					old=$(cut -d \" -f 2 <<< "$old")
					G_CONFIG_INJECT 'setenv bootrootfs "' "setenv bootrootfs \"$old console=$INPUT_ADDITIONAL,115200n8\"" /boot/boot.ini

				# - Armbian: armbianEnv.txt only allows to toggle a fixed serial console depending on device
				elif (( $ARMBIAN )); then

					grep -q "console=$INPUT_ADDITIONAL" /boot/boot.cmd || return 0
					if grep -qE 'console=(display|both)' $FP_UENV; then

						G_CONFIG_INJECT 'console=' 'console=both' $FP_UENV

					else

						G_CONFIG_INJECT 'console=' 'console=serial' $FP_UENV

					fi

				# - PINE A64: On Armbian ttyS0 boot output is forced and custom console is not possible via armbianEnv.txt
				elif (( $G_HW_MODEL == 40 )); then

					[[ ! -f $FP_UENV ]] || grep -q "console=$INPUT_ADDITIONAL" $FP_UENV && return 0
					echo "console=$INPUT_ADDITIONAL,115200n8" >> $FP_UENV

				fi

			# Enable for all detected Serial/UART devices
			else

				# ttyFIQ[0-9]: https://github.com/MichaIng/DietPi/issues/1829#issuecomment-398302497
				for i in /dev/tty{S,AMA,SAC}[0-9]
				do
					[[ -e $i ]] || continue
					INPUT_ADDITIONAL=${i/\/dev\/} Serial_Main
				done

				# On RPi enable primary UART device
				(( $G_HW_MODEL > 9 )) || G_CONFIG_INJECT 'enable_uart=' 'enable_uart=1' /boot/config.txt

				# Update dietpi.txt global var
				G_CONFIG_INJECT 'CONFIG_SERIAL_CONSOLE_ENABLE=' 'CONFIG_SERIAL_CONSOLE_ENABLE=1' /boot/dietpi.txt

			fi

		#-------------------------------------------------------------------------------------
		# Disable
		elif [[ $INPUT_DEVICE_VALUE == 'disable' ]]; then

			# Disable for specific Serial/UART device
			if [[ $INPUT_ADDITIONAL ]]; then

				G_DIETPI-NOTIFY 2 "Disabling serial-getty on: /dev/$INPUT_ADDITIONAL"
				# Stop getty only if not currently attached, failsafe estimation in case of symlinks
				local stop='--now'
				[[ $(readlink -f "$(tty)") == $(readlink -f "/dev/$INPUT_ADDITIONAL") ]] && stop=
				systemctl disable "$stop" "serial-getty@$INPUT_ADDITIONAL"
				# Place a mask only if device exists
				[[ -e /dev/$INPUT_ADDITIONAL ]] && systemctl mask "serial-getty@$INPUT_ADDITIONAL"

				# Disable boot messages depending on device
				# - RPi
				if (( $G_HW_MODEL < 10 )); then

					sed -Ei "s/[[:blank:]]*console=${INPUT_ADDITIONAL}[^[:blank:]]*([[:blank:]]*$)?//" /boot/cmdline.txt

				# - Odroid C1/C2/XU4
				elif (( $G_HW_MODEL < 12 )); then

					sed -i "s/[[:blank:]]*console=${INPUT_ADDITIONAL}[^\"[:blank:]]*//" /boot/boot.ini

				elif (( $ARMBIAN )); then

					grep -q "console=$INPUT_ADDITIONAL" /boot/boot.cmd || return 0
					if grep -qE 'console=(display|both)' $FP_UENV; then

						G_CONFIG_INJECT 'console=' 'console=display' $FP_UENV

					else

						G_CONFIG_INJECT 'console=' 'console=none' $FP_UENV

					fi

				# - PINE A64: On Armbian ttyS0 boot output is forced and custom console is not possible via armbianEnv.txt
				elif (( $G_HW_MODEL == 40 )); then

					sed -i "/^[[:blank:]]*console=${INPUT_ADDITIONAL}[^\"[:blank:]]*[[:blank:]]*$/d" $FP_UENV # New style: One variable each line
					sed -i "s/[[:blank:]]*console=${INPUT_ADDITIONAL}[^\"[:blank:]]*//" $FP_UENV # Old style: Multiple variables possible each line

				fi

			# Disable for all detected Serial/UART devices
			else

				# ttyFIQ[0-9]: https://github.com/MichaIng/DietPi/issues/1829#issuecomment-398302497
				for i in /dev/tty{S,AMA,SAC}[0-9]
				do
					[[ -e $i ]] || continue
					INPUT_ADDITIONAL=${i/\/dev\/} Serial_Main
				done

				# Cleanup: Disable for left non-existent devices
				for i in /etc/systemd/system/getty.target.wants/serial-getty@*
				do
					[[ -e $i ]] || continue
					i=${i%.service}
					INPUT_ADDITIONAL=${i##*@} Serial_Main
				done

				# On RPi disable primary UART device
				(( $G_HW_MODEL > 9 )) || G_CONFIG_INJECT 'enable_uart=' 'enable_uart=0' /boot/config.txt

				# Update dietpi.txt global var
				G_CONFIG_INJECT 'CONFIG_SERIAL_CONSOLE_ENABLE=' 'CONFIG_SERIAL_CONSOLE_ENABLE=0' /boot/dietpi.txt

			fi

		else

			Unknown_Input_Mode

		fi

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# soundcard
	#/////////////////////////////////////////////////////////////////////////////////////
	# Disable all sound cards and reset all settings
	Soundcard_Reset_All(){

		G_DIETPI-NOTIFY 2 'Resetting all sound card settings...'

		# All
		SOUNDCARD_TARGET_CARD=0
		SOUNDCARD_TARGET_DEVICE=0
		ALSA_PLUG_ENABLED=0
		ALSA_EQ_ENABLED=0

		# - Remove previous asound.conf
		[[ -f '/etc/asound.conf' ]] && G_EXEC rm /etc/asound.conf

		# - Remove stored amixer state
		[[ -f '/var/lib/alsa/asound.state' ]] && G_EXEC rm /var/lib/alsa/asound.state

		# - Reset active amixer state ("-g" option has been added upstream: https://github.com/alsa-project/alsa-utils/issues/75)
		[[ $INPUT_DEVICE_VALUE != 'none' && -f '/proc/asound/cards' && $(</proc/asound/cards) ]] && alsactl init

		# HW specific
		# - RPi
		if (( $G_HW_MODEL < 10 )); then

			Soundcard_Reset_RPi

		# - Odroid
		elif (( $G_HW_MODEL < 20 )); then

			Soundcard_Reset_Odroid

		# - H3
		elif (( $G_HW_CPUID == 1 )); then

			Soundcard_Reset_H3

		# - Sparky SBC
		elif (( $G_HW_MODEL == 70 )); then

			Soundcard_Reset_SparkySBC

		# - ASUS TB
		elif (( $G_HW_MODEL == 52 )); then

			Soundcard_Reset_Asus

		fi

	}

	Soundcard_Reset_RPi(){

		# Remove known sound card device tree overlays
		sed -i '/^[[:blank:]]*dtoverlay=hifiberry-/d' /boot/config.txt
		sed -i '/^[[:blank:]]*dtoverlay=iqaudio-/d' /boot/config.txt
		sed -i '/^[[:blank:]]*dtoverlay=justboom-/d' /boot/config.txt
		sed -i '/^[[:blank:]]*dtoverlay=allo-/d' /boot/config.txt
		sed -i '/^[[:blank:]]*dtoverlay=rpi-dac/d' /boot/config.txt
		sed -i '/^[[:blank:]]*dtoverlay=i-sabre-/d' /boot/config.txt
		sed -i '/^[[:blank:]]*dtoverlay=dionaudio-/d' /boot/config.txt
		sed -i '/^[[:blank:]]*dtoverlay=googlevoicehat-soundcard/d' /boot/config.txt
		sed -i '/^[[:blank:]]*dtoverlay=applepi-/d' /boot/config.txt

		# Disable I2S
		sed -i '/^[[:blank:]]*dtparam=i2s=/d' /boot/config.txt

		# Disable HDMI drive
		G_EXEC sed -Ei 's/^[[:blank:]]*(hdmi_drive(:[01])?=.*$)/#\1/' /boot/config.txt

		# Remove overlays to disable HDMI audio and 3.5mm jack
		G_EXEC sed -Ei '/^[[:blank:]]*dtoverlay=dietpi-disable_(hdmi_audio|headphones)/d' /boot/config.txt
		[[ -f '/boot/overlays/dietpi-disable_hdmi_audio.dtbo' ]] && G_EXEC rm /boot/overlays/dietpi-disable_hdmi_audio.dtbo
		[[ -f '/boot/overlays/dietpi-disable_headphones.dtbo' ]] && G_EXEC rm /boot/overlays/dietpi-disable_headphones.dtbo

		# Disable onboard sound
		G_CONFIG_INJECT 'dtparam=audio=' 'dtparam=audio=off' /boot/config.txt

	}

	Soundcard_Reset_Odroid(){

		[[ -f '/var/lib/dietpi/postboot.d/c2_smp.sh' ]] && rm /var/lib/dietpi/postboot.d/c2_smp.sh

		# HiFi shield plus
		sed -i '/^[[:blank:]]*snd-soc-pcm5102/d' /etc/modules
		sed -i '/^[[:blank:]]*snd-soc-odroid-dac/d' /etc/modules

		# HiFi shield 2
		sed -i '/^[[:blank:]]*snd-soc-pcm512x/d' /etc/modules
		sed -i '/^[[:blank:]]*snd-soc-pcm512x-i2c/d' /etc/modules
		sed -i '/^[[:blank:]]*snd-soc-odroid-dac2/d' /etc/modules
		if [[ -f '/etc/systemd/system/odroid-hifishield2.service' ]]; then

			systemctl disable --now odroid-hifishield2
			rm /etc/systemd/system/odroid-hifishield2.service

		fi
		[[ -d '/etc/systemd/system/odroid-hifishield2.service.d' ]] && rm -R /etc/systemd/system/odroid-hifishield2.service.d

	}

	Soundcard_Reset_H3(){

		# Set HDMI
		SOUNDCARD_TARGET_CARD=1
		[[ $INPUT_DEVICE_VALUE != 'none' && -f '/proc/asound/cards' && $(</proc/asound/cards) ]] && amixer -c 0 set 'Audio lineout' mute

	}

	Soundcard_Reset_Asus(){

		# Set HDMI
		SOUNDCARD_TARGET_CARD=1

	}

	Soundcard_Reset_SparkySBC(){

		# Allo Piano DAC
		sed -i '/^[[:blank:]]*snd-soc-allo-piano-dac/d' /etc/modules

		# Disable USB 1.1 compat
		sed -i 's/aotg.aotg1_speed=1/aotg.aotg1_speed=0/' $FP_UENV

		# Set HDMI
		SOUNDCARD_TARGET_DEVICE=1
		[[ $INPUT_DEVICE_VALUE != 'none' && -f '/proc/asound/cards' && $(</proc/asound/cards) ]] && amixer -c 0 set 'audio output mode switch' hdmi

	}

	Soundcard_Main(){

		#-----------------------------------------------------------------------------
		# An input is required
		[[ $INPUT_DEVICE_VALUE ]] || Unknown_Input_Mode
		#-----------------------------------------------------------------------------
		# Failsafe: Assure installed alsa-utils, if soundcard has been selected
		[[ $INPUT_DEVICE_VALUE == 'none' ]] || G_AG_CHECK_INSTALL_PREREQ alsa-utils
		# Always reset soundcards and revert back to defaults
		Soundcard_Reset_All
		# Print info
		G_DIETPI-NOTIFY 2 'Applying new sound card settings...'
		# Save selection to dietpi.txt
		G_CONFIG_INJECT 'CONFIG_SOUNDCARD=' "CONFIG_SOUNDCARD=$INPUT_DEVICE_VALUE" /boot/dietpi.txt
		# Return now if no soundcard has been selected
		[[ $INPUT_DEVICE_VALUE == 'none' ]] && return
		#-----------------------------------------------------------------------------
		# Apply specific asound.conf and additional settings
		# - ALSA equalizer enabled?
		if [[ $INPUT_DEVICE_VALUE == *'-eq' ]]; then

			ALSA_EQ_ENABLED=1
			# Remove suffic so it doesn't get sent as a dtoverlay on RPi
			INPUT_DEVICE_VALUE=${INPUT_DEVICE_VALUE%-eq}

		# - ALSA automatic conversion (plug) enabled?
		elif [[ $INPUT_DEVICE_VALUE == *'-plug' ]]; then

			ALSA_PLUG_ENABLED=1
			# Remove suffic so it doesn't get sent as a dtoverlay on RPi
			INPUT_DEVICE_VALUE=${INPUT_DEVICE_VALUE%-plug}

		fi

		# Workaround for RPi VC4 full KMS driver
		# - RPi: An additional HDMI sound device exists as card 0: https://github.com/MichaIng/DietPi/issues/3356#issuecomment-578215611
		(( $G_HW_MODEL < 10 )) && grep -q '^[[:blank:]]*dtoverlay=vc4-kms-v3d' /boot/config.txt && ((SOUNDCARD_TARGET_CARD++))
		# - RPi4: card 1 is additionally used for the second HDMI port: https://github.com/MichaIng/DietPi/issues/4059
		(( $G_HW_MODEL == 4 )) && grep -q '^[[:blank:]]*dtoverlay=vc4-kms-v3d-pi4' /boot/config.txt && ((SOUNDCARD_TARGET_CARD++))

		# - Cards
		case "$INPUT_DEVICE_VALUE" in

			# --------------- Generic ---------------
			# Specific card + device, e.g. from auto-detection
			hw:*)

				SOUNDCARD_TARGET_CARD=$(mawk -F, '{print $1}' <<< "${INPUT_DEVICE_VALUE#hw:}")
				SOUNDCARD_TARGET_DEVICE=$(mawk -F, '{print $2}' <<< "${INPUT_DEVICE_VALUE#hw:}")

			;;

			# Auto detect USB DAC
			usb-dac*)

				local usb_detection_card_index=$([[ -f '/proc/asound/cards' ]] && mawk '/USB/ && $1 == /[0-9]/ {print $1;exit}' /proc/asound/cards)
				if [[ $usb_detection_card_index ]]; then

					SOUNDCARD_TARGET_CARD=$usb_detection_card_index
					SOUNDCARD_TARGET_DEVICE=0

					# Sparky SBC
					if (( $G_HW_MODEL == 70 )); then

						# USB 1.1 compat mode
						[[ $INPUT_DEVICE_VALUE == *'1.1' ]] && G_EXEC sed -i 's/aotg\.aotg1_speed=0/aotg.aotg1_speed=1/' $FP_UENV

					# Odroid C2: https://github.com/MichaIng/DietPi/issues/2101
					elif (( $G_HW_MODEL == 12 )); then

						cat << '_EOF_' > /var/lib/dietpi/postboot.d/c2_smp.sh
#!/bin/dash
echo 4 > /proc/irq/63/smp_affinity
echo 8 > /proc/irq/62/smp_affinity
_EOF_
						. /var/lib/dietpi/postboot.d/c2_smp.sh

					fi

				# Not found
				else

					G_DIETPI-NOTIFY 1 'Unable to find any USB DAC on your system, reverting to "none"...'
					EXIT_CODE=1
					G_CONFIG_INJECT 'CONFIG_SOUNDCARD=' 'CONFIG_SOUNDCARD=none' /boot/dietpi.txt
					return

				fi

			;;

			# Intel SST DSP
			intel-sst-dsp) G_AG_CHECK_INSTALL_PREREQ 'firmware-intel-sound';;

			# --------------- Sparky SBC ------------
			# Allo Piano DAC (firmware + module)
			#	snd-soc-allo-piano-dac
			#	snd-soc-allo-piano-dac-plus (2.1)
			snd-soc-allo-piano-dac*)

				if [[ ! -d '/lib/firmware/allo' ]]
				then
					local url='https://raw.githubusercontent.com/sparky-sbc/sparky-test/master/piano-firmware/piano-firmware.tar'
					G_CHECK_URL "$url"
					G_EXEC curl -sSfL "$url" -o package.tar
					G_EXEC tar -xf package.tar -C /lib/
					G_EXEC_NOHALT=1 G_EXEC rm package.tar
				fi

				G_CONFIG_INJECT "$INPUT_DEVICE_VALUE" "$INPUT_DEVICE_VALUE" /etc/modules
				G_EXEC modprobe "$INPUT_DEVICE_VALUE"
				SOUNDCARD_TARGET_CARD=1
				SOUNDCARD_TARGET_DEVICE=0
				G_EXEC amixer -c 0 set 'audio output mode switch' i2s

			;;

			# Allo Cheapo
			#	allo-cheapo-analogue	# 3.5mm/RCA
			#	allo-cheapo-optical	# Optical out
			allo-cheapo*)

				SOUNDCARD_TARGET_CARD=0
				SOUNDCARD_TARGET_DEVICE=0

				# Vol
				G_EXEC amixer –c 0 set 'DAC PA' 35

				if [[ $INPUT_DEVICE_VALUE == 'allo-cheapo-analogue' ]]; then

					G_EXEC amixer -c 0 set 'audio output mode switch' i2s

				else

					G_EXEC amixer -c 0 set 'audio output mode switch' spdif
					SOUNDCARD_TARGET_DEVICE=2

				fi

			;;

			# --------------- RPi -------------------
			# Onboard
			#	rpi-bcm2835-auto
			#	rpi-bcm2835-3.5mm
			#	rpi-bcm2835-hdmi
			rpi-bcm2835-*)

				# Enable onboard audio
				G_CONFIG_INJECT 'dtparam=audio=' 'dtparam=audio=on' /boot/config.txt

				# Force 3.5mm out?
				if [[ $INPUT_DEVICE_VALUE == *'3.5mm' ]]; then

					# Disable HDMI audio via dtoverlay
					G_EXEC_DESC='Compiling device tree overlay: /boot/overlays/dietpi-disable_hdmi_audio.dtbo'
					G_EXEC eval 'dtc -I dts -O dtb -o /boot/overlays/dietpi-disable_hdmi_audio.dtbo <<< '\''/dts-v1/;
/plugin/;
/ {
	compatible = "brcm,bcm2835";
	fragment@0 {
		target = <&audio>;
		__overlay__ {
			brcm,disable-hdmi = <1>;
		};
	};
};'\'''
					G_CONFIG_INJECT 'dtoverlay=dietpi-disable_hdmi_audio' 'dtoverlay=dietpi-disable_hdmi_audio' /boot/config.txt

				# Force HDMI output?
				elif [[ $INPUT_DEVICE_VALUE == *'hdmi' ]]; then

					# Disable headphones via dtoverlay
					G_EXEC_DESC='Compiling device tree overlay: /boot/overlays/dietpi-disable_headphones.dtbo'
					G_EXEC eval 'dtc -I dts -O dtb -o /boot/overlays/dietpi-disable_headphones.dtbo <<< '\''/dts-v1/;
/plugin/;
/ {
	compatible = "brcm,bcm2835";
	fragment@0 {
		target = <&audio>;
		__overlay__ {
			brcm,disable-headphones = <1>;
		};
	};
};'\'''
					G_CONFIG_INJECT 'dtoverlay=dietpi-disable_headphones' 'dtoverlay=dietpi-disable_headphones' /boot/config.txt
					G_CONFIG_INJECT 'hdmi_drive=' 'hdmi_drive=2' /boot/config.txt
					(( $G_HW_MODEL == 4 )) && G_CONFIG_INJECT 'hdmi_drive:1=' 'hdmi_drive:1=2' /boot/config.txt 'hdmi_drive='

				fi

			;;

			# Allo Piano DAC (DSP firmware + dtoverlay)
			#	allo-piano-dac-pcm512x-audio
			#	allo-piano-dac-plus-pcm512x-audio (2.1)
			allo-piano-dac*)

				if [[ ! -d '/lib/firmware/allo' ]]
				then
					local url='https://github.com/allocom/piano-firmware/archive/master.tar.gz'
					G_CHECK_URL "$url"
					G_EXEC curl -sSfL "$url" -o package.tar.gz
					G_EXEC tar -xf package.tar.gz
					G_EXEC_NOHALT=1 G_EXEC rm package.tar.gz
					G_EXEC mkdir -p /lib/firmware
					G_EXEC mv piano-firmware-master/lib/firmware/allo /lib/firmware/
					G_EXEC_NOHALT=1 G_EXEC rm -R piano-firmware-master
				fi

				G_CONFIG_INJECT "dtoverlay=$INPUT_DEVICE_VALUE" "dtoverlay=$INPUT_DEVICE_VALUE" /boot/config.txt

			;;

			# dtoverlay
			#	hifiberry-*
			#	JustBoom-[dac|digi|both]
			#	allo-boss-dac-pcm512x-audio
			#	allo-boss2-dac-audio
			#	allo-digione
			#	allo-katana-dac-audio
			#	rpi-dac
			#	i-sabre-q2m
			#	applepi-dac
			#	iqaudio-*
			#	dionaudio-loco(-v2)
			hifiberry-*|justboom-*|allo-*|rpi-dac|i-sabre-q2m|applepi*|iqaudio-*|dionaudio-loco*)

				# Enable dtoverlay
				G_CONFIG_INJECT "dtoverlay=$INPUT_DEVICE_VALUE" "dtoverlay=$INPUT_DEVICE_VALUE" /boot/config.txt

			;;

			# dtoverlay + I2S
			#	googlevoicehat-soundcard
			googlevoicehat-soundcard*)

				# Enable dtoverlay + I2S
				G_CONFIG_INJECT 'dtparam=i2s=' 'dtparam=i2s=on' /boot/config.txt
				G_CONFIG_INJECT "dtoverlay=$INPUT_DEVICE_VALUE" "dtoverlay=$INPUT_DEVICE_VALUE" /boot/config.txt

			;;

			# --------------- Odroid ----------------
			odroid-hifishield-plus)

				G_CONFIG_INJECT 'snd-soc-pcm5102' 'snd-soc-pcm5102' /etc/modules
				G_CONFIG_INJECT 'snd-soc-odroid-dac' 'snd-soc-odroid-dac' /etc/modules
				G_EXEC modprobe snd-soc-pcm5102 snd-soc-odroid-dac

				SOUNDCARD_TARGET_CARD=1

			;;

			odroid-hifishield-2)

				G_CONFIG_INJECT 'aml_i2c' 'aml_i2c' /etc/modules
				G_CONFIG_INJECT 'snd-soc-pcm512x' 'snd-soc-pcm512x' /etc/modules
				G_CONFIG_INJECT 'snd-soc-pcm512x-i2c' 'snd-soc-pcm512x-i2c' /etc/modules
				G_CONFIG_INJECT 'snd-soc-odroid-dac2' 'snd-soc-odroid-dac2' /etc/modules
				G_EXEC modprobe aml_i2c snd-soc-pcm512x snd-soc-pcm512x-i2c snd-soc-odroid-dac2

				SOUNDCARD_TARGET_CARD=1

				cat << _EOF_ > /etc/systemd/system/odroid-hifishield2.service
[Unit]
Description=odroid-hifishield2
After=local-fs.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/dash -c 'echo pcm5242 0x4c > /sys/class/i2c-adapter/i2c-1/new_device'
ExecStart=$(command -v amixer) -c 1 set Analogue 0
ExecStart=$(command -v amixer) -c 1 set Digital 201
ExecStart=$(command -v amixer) -c 1 set Deemphasis on

[Install]
WantedBy=sound.target
_EOF_
				G_EXEC systemctl daemon-reload
				G_EXEC systemctl enable --now odroid-hifishield2

			;;

			# --------------- H3 --------------------
			h3-analogue)

				G_EXEC amixer -c 0 set 'Audio lineout' unmute
				SOUNDCARD_TARGET_CARD=0

			;;

			# --------------- NanoPi M2/M3 ----------
			s5pxx18-hdmi)

				SOUNDCARD_TARGET_CARD=1

			;;

			# --------------- ASUS TB ---------------
			asus-tb-analogue)

				SOUNDCARD_TARGET_CARD=0
				SOUNDCARD_TARGET_DEVICE=2

			;;

		esac

		# - Apply asound.conf
		if [[ $INPUT_DEVICE_VALUE == 'googlevoicehat-soundcard'* ]]; then

			cat << '_EOF_' > /etc/asound.conf
pcm.softvol {
	type softvol
	slave.pcm dmix
	control {
		name Master
		card 0
	}
}

pcm.micboost {
	type route
	slave.pcm dsnoop
	ttable {
		0.0 30.0
		1.1 30.0
	}
}

pcm.!default {
	type asym
	playback.pcm "plug:softvol"
	capture.pcm "plug:micboost"
}

ctl.!default {
	type hw
	card 0
}
_EOF_
		elif (( $ALSA_EQ_ENABLED )); then

			G_AG_CHECK_INSTALL_PREREQ libasound2-plugin-equal
			# Pre-create config dir
			G_EXEC mkdir -p /var/lib/dietpi/dietpi-config
			G_EXEC chmod 0775 /var/lib/dietpi/dietpi-config
			G_EXEC chown dietpi:dietpi /var/lib/dietpi/dietpi-config
			cat << _EOF_ > /etc/asound.conf
pcm.!default {
	type plug
	slave.pcm {
		type equal
		slave.pcm {
			type plug
			slave.pcm {
				type hw
				card $SOUNDCARD_TARGET_CARD
				device $SOUNDCARD_TARGET_DEVICE
			}
		}
		controls "/var/lib/dietpi/dietpi-config/.alsaequal.bin"
	}
}

ctl.eq {
	type equal
	controls "/var/lib/dietpi/dietpi-config/.alsaequal.bin"
}

ctl.!default {
	type hw
	card $SOUNDCARD_TARGET_CARD
}
_EOF_
		elif (( $ALSA_PLUG_ENABLED )); then

			cat << _EOF_ > /etc/asound.conf
pcm.!default {
	type plug
	slave.pcm {
		type hw
		card $SOUNDCARD_TARGET_CARD
		device $SOUNDCARD_TARGET_DEVICE
	}
}

ctl.!default {
	type hw
	card $SOUNDCARD_TARGET_CARD
}
_EOF_
		else

			cat << _EOF_ > /etc/asound.conf
pcm.!default {
	type hw
	card $SOUNDCARD_TARGET_CARD
	device $SOUNDCARD_TARGET_DEVICE
}

ctl.!default {
	type hw
	card $SOUNDCARD_TARGET_CARD
}
_EOF_
		fi

		# Store control states once to assure they are not lost on ungraceful shutdown
		# - On RPi, this can fail, fake success for now until we find time to further investigate the when and why: https://github.com/MichaIng/DietPi/issues/4306
		(( $G_HW_MODEL > 9 )) || G_EXEC_NOFAIL=1
		G_EXEC alsactl -g store

		# Buster: Avoid alsa-state.service start if its config file does not exist: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=932209
		(( $G_DISTRO == 5 )) || return
		G_EXEC mkdir -p /etc/systemd/system/alsa-state.service.d
		echo -e '[Unit]\nConditionPathExists=\nConditionPathExists=/etc/alsa/state-daemon.conf' > /etc/systemd/system/alsa-state.service.d/dietpi.conf

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Main Loop
	#/////////////////////////////////////////////////////////////////////////////////////
	#-----------------------------------------------------------------------------------
	G_DIETPI-NOTIFY 3 "$G_PROGRAM_NAME" "$INPUT_DEVICE_NAME ($INPUT_DEVICE_VALUE)"

	#-----------------------------------------------------------------------------------
	if [[ $INPUT_DEVICE_NAME == 'soundcard' ]]; then

		Soundcard_Main

	elif [[ $INPUT_DEVICE_NAME == 'serialconsole' ]]; then

		Serial_Main

	elif [[ $INPUT_DEVICE_NAME == 'bluetooth' ]]; then

		Bluetooth_Main || EXIT_CODE=1

	elif [[ $INPUT_DEVICE_NAME == 'wifimodules' ]]; then

		Wifi_Modules_Main

	elif [[ $INPUT_DEVICE_NAME == 'enableipv6' ]]; then

		Enable_IPv6

	elif [[ $INPUT_DEVICE_NAME == 'preferipv4' ]]; then

		Prefer_IPv4

	elif [[ $INPUT_DEVICE_NAME == 'wificountrycode' ]]; then

		Wifi_Countrycode_Main

	elif [[ $INPUT_DEVICE_NAME == 'i2c' ]]; then

		I2c_Main

	elif [[ $INPUT_DEVICE_NAME == 'spi' ]]; then

		SPI_Main

	elif [[ $INPUT_DEVICE_NAME == 'lcdpanel' ]]; then

		Lcd_Panel_Main

	elif [[ $INPUT_DEVICE_NAME == 'rpi-opengl' ]]; then

		RPi_OpenGL_Main

	elif [[ $INPUT_DEVICE_NAME == 'eth-forcespeed' ]]; then

		Eth_Force_Speed_Main

	elif [[ $INPUT_DEVICE_NAME == 'remoteir' ]]; then

		RemoteIR_Main

	elif [[ $INPUT_DEVICE_NAME == 'gpumemsplit' ]]; then

		Gpu_Memory_Split_Main

	elif [[ $INPUT_DEVICE_NAME == 'rpi-camera' ]]; then

		RPi_Camera_Main

	elif [[ $INPUT_DEVICE_NAME == 'rpi3_usb_boot' ]]; then

		RPi_USB_Boot_Main

	elif [[ $INPUT_DEVICE_NAME == 'rpi-eeprom' ]]; then

		RPi_EEPROM

	elif [[ $INPUT_DEVICE_NAME == 'headless' ]]; then

		Headless_Main

	else

		Unknown_Input_Name

	fi

	#-----------------------------------------------------------------------------------
	G_DIETPI-NOTIFY -1 $EXIT_CODE "$INPUT_DEVICE_NAME $INPUT_DEVICE_VALUE"
	#-----------------------------------------------------------------------------------
	exit $EXIT_CODE
	#-----------------------------------------------------------------------------------
}
